package net.khoroshev.wschat.service;

import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;

import net.khoroshev.wschat.model.ChatHistoryEntry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.messaging.core.MessageSendingOperations;
import org.springframework.messaging.simp.BrokerAvailabilityEvent;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;

@Service
public class ChatService implements ApplicationListener<BrokerAvailabilityEvent>{

    private static Log log = LogFactory.getLog(ChatService.class);

    private final MessageSendingOperations<String> messagingTemplate;
    
    private AtomicBoolean brokerAvailable = new AtomicBoolean();
    
    @Autowired
    DataSource dataSource;
    
    @Autowired
    public ChatService(MessageSendingOperations<String> messagingTemplate) {
        super();
        this.messagingTemplate = messagingTemplate;
    }
    @Override
    public void onApplicationEvent(BrokerAvailabilityEvent event) {
        this.brokerAvailable.set(event.isBrokerAvailable());
    }
    
    public void onMessage(ChatHistoryEntry entry) {
        if (this.brokerAvailable.get()) {
            log.debug("New message sends to history. " + entry) ;
            this.messagingTemplate.convertAndSend("/queue/chat.history", entry);
            try {
                Connection con = dataSource.getConnection();
                PreparedStatement st = con.prepareStatement(
                    "INSERT INTO CHAT_HISTORY (MTIME, USER_ID, MESSAGE) " +
                    "SELECT ?, USER_ID, ? FROM USERS " +
                    "WHERE USERNAME = ?"
                );
                st.setTimestamp(1, new Timestamp(entry.getTime().getTime()));
                st.setString(2, entry.getText());
                st.setString(3, entry.getUsername());
                st.executeUpdate();
            } catch (SQLException e) {
                log.error("Can't write message to DB", e);
            }
        }
    }
    
    public Collection<ChatHistoryEntry> getLastMessages (int what) {
        Collection<ChatHistoryEntry> result = new ArrayList<>();
        try {
            Connection con = dataSource.getConnection();
            PreparedStatement st = con.prepareStatement(
                    "SELECT MTIME, USER, MESSAGE FROM CHAT_HISTORY LIMIT ?"
                );
            st.setInt(1, what);
            ResultSet rs = st.executeQuery();
            while (rs.next()) {
                result.add(mapHistoryEntry(rs));
            }
        } catch (SQLException e) {
            log.error("Can't read messages from DB", e);
        }
        return result;
    }
    
    private ChatHistoryEntry mapHistoryEntry(ResultSet rs) throws SQLException {
        String username = rs.getString("user");
        java.util.Date time = rs.getDate("mtime");
        String text = rs.getString("message");
        ChatHistoryEntry result = new ChatHistoryEntry(username, time, text);
        return result ;
    }
}
